package job

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"go-api/internal/dao/model"
	"io"
	"net/http"
	"time"

	"github.com/zeromicro/go-zero/core/logx"
	"gorm.io/gorm"

	"go-api/internal/dao/model/mysql"
	"go-api/internal/dao/schema"
	"go-api/internal/svc"
)

type VideoGenerateCron struct {
	ctx       context.Context
	svcCtx    *svc.ServiceContext
	db        *gorm.DB
	client    *http.Client
	batchSize int
}

func NewVideoGenerateCron(ctx context.Context, svcCtx *svc.ServiceContext) *VideoGenerateCron {
	return &VideoGenerateCron{
		ctx:       ctx,
		svcCtx:    svcCtx,
		db:        svcCtx.DbSelect.GetDb(ctx, model.DB),
		client:    getHTTPClient(),
		batchSize: 200,
	}
}

func (c *VideoGenerateCron) RunVideoGenerateJob() {
	for {
		// 从 Redis 队列中获取任务
		taskData, err := c.svcCtx.RedisClient.LPop(c.ctx, "video_generate_queue").Result()
		if err != nil {
			//logx.Errorf("从 Redis 队列获取任务失败: %v", err)
			time.Sleep(1 * time.Second)
			continue
		}
		if taskData == "" {
			time.Sleep(1 * time.Second)
			continue
		}

		var task schema.CustomerOneTouchVideoTask
		err = json.Unmarshal([]byte(taskData), &task)
		if err != nil {
			logx.Errorf("解析任务数据失败: %v", err)
			continue
		}
		c.processTask(&task)
	}
}

func (c *VideoGenerateCron) processTask(task *schema.CustomerOneTouchVideoTask) {
	// 获取任务详情 这里需要根据task.ID查询CustomerOneTouchVideoTaskInfo表，得到的结果是list； 多条数据；
	infos, err := mysql.NewCustomerOneTouchVideoTaskInfoModel(c.ctx, c.svcCtx).FindInfosByTaskID(task.ID)
	if err != nil {
		logx.Errorf("获取任务详情失败: %v", err)
		return
	}

	for _, info := range infos {
		// 调用视频生成 API
		reqData := c.buildRequestData(info)
		resp, err := c.client.Post("http://video.yunshiyouke.com.cn/videoclips/Timeline/submitJob",
			"application/json", io.NopCloser(bytes.NewBuffer(reqData)))
		if err != nil {
			logx.Errorf("API 请求失败: %v", err)
			continue
		}
		defer resp.Body.Close()

		var result map[string]interface{}
		if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
			logx.Errorf("响应解析失败: %v", err)
			continue
		}

		// 更新任务状态
		updateData := map[string]interface{}{
			"job_id":     result["JobId"],
			"media_id":   result["MediaId"],
			"project_id": result["ProjectId"],
			"request_id": result["RequestId"],
			"status":     2, // 生成中状态
		}
		if err := mysql.NewCustomerOneTouchVideoTaskInfoModel(c.ctx, c.svcCtx).UpdateById(info.ID, updateData); err != nil {
			logx.Errorf("更新任务状态失败: %v", err)
		}

		// 发布任务到结果查询队列
		payload, err := json.Marshal(info)
		if err != nil {
			logx.Errorf("JSON 序列化任务失败: %v", err)
			continue
		}
		err = c.svcCtx.RedisClient.RPush(c.ctx, "video_result_queue", payload).Err()
		if err != nil {
			logx.Errorf("将任务推送到结果查询队列失败: %v", err)
		}
	}
}

func (c *VideoGenerateCron) buildRequestData(info *schema.CustomerOneTouchVideoTaskInfo) []byte {
	// 根据实际 API 需求构造请求体
	data := map[string]interface{}{
		"title":   info.Title,
		"content": info.Captions,
		"tags":    info.Tag,
	}
	jsonData, _ := json.Marshal(data)
	return jsonData
}

// 公共方法
func (c *VideoGenerateCron) acquireLock(lockKey string) bool {
	return c.svcCtx.RedisClient.SetNX(c.ctx,
		fmt.Sprintf("cron_lock:%s", lockKey),
		1,
		4*time.Minute).Val()
}
